package model;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Dustin & Maik
 */
public class WebPage extends Thread {
    public final static String[] BAD_CHARACTERS = {"mailto:", "javascript", "[", "]", "_", "+", "{", "}"};
    private Pattern p = Pattern.compile("(.*)(href|src)(=\")(.*?)(\".*)");
    private Matcher m;
    private URL url;
    private File outputFile;
    protected byte[] content;
    private URLConnection urlConnection;
    private int maxSize;
    private boolean done;

    public WebPage(URL anURL) throws IOException {
        url = anURL;
        urlConnection = url.openConnection();

        String filepath = "";
        filepath += url.getHost();
        filepath += url.getPath();
        filepath += url.getPath().matches(".*/$") ? "index.html" : "";

        outputFile = new File(filepath);
        outputFile.getParentFile().mkdirs();
    }

    public void run() {
        System.out.println("Thread started " + WebSiteGetter.threads.size());
        while(!done) {
            try {
                readLinks(WebSiteGetter.fetchedList);
            } catch (IOException ex) {
                ex.printStackTrace();
            } catch (URISyntaxException ex) {
                ex.printStackTrace();
            }
            yield();
        }
    }


    /**
     * Command to check if the given String contains "bad character" defined in BAD_CHARACTERS
     * @param link the String to check
     * @return boolean if this String contains bad characters
     */
    private boolean filterLink(String link) {
        boolean contains = false;
        for (int i = 0; i < BAD_CHARACTERS.length; i++) {
            if (!contains && link.contains(BAD_CHARACTERS[i])) {
                contains = true;
            }
        }
        return contains;
    }

    private synchronized void addToList(ArrayList<String> list, String data) {
        list.add(data);
    }

    /**
     * Command to read all links of this webpage and store them in an ArrayList
     * @param urlList the list which contains all links found
     * @throws IOException
     * @throws URISyntaxException
     */
    public void readLinks(ArrayList<String> fetchedList) throws IOException, URISyntaxException {
        String opgebouwdeContent = "";

        addToList(fetchedList, url.toString());
        System.out.println("added " + url.toString() + " to fetch");
        urlConnection = url.openConnection();
        try {
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
            String inputLine;
            while ((inputLine = bufferedReader.readLine()) != null) {
                m = p.matcher(inputLine);
                if (m.matches()) {
                    m.reset();
                    while (m.find()) {
                        String link = (m.group(4).trim());
                        String codeLink = link;
                        if (!m.group(2).equals("src")) {
                            // linkjes + .html
                            if (!filterLink(link)) {
                                URI currentURI = new URI(link);
                                if (!(currentURI.toString().startsWith(".")) && !currentURI.isAbsolute() && (link.endsWith(".html") || link.endsWith("/"))) {
                                    if (link.length() > 1) {
                                        if (!link.startsWith("http://")) {
                                            if (link.startsWith("/") && link.endsWith("/")) {
                                                link = "http://" + url.getHost() + link + "index.html";
                                            } else if (link.startsWith("/") && link.endsWith("html")) {
                                                link = "http://" + url.getHost() + link;
                                            } else if (link.startsWith("/")) {
                                                link = "http://" + url.getHost() + link + "/index.html";
                                            } else if (link.endsWith("/")) {
                                                link = "http://" + url.getHost() + "/" + link;
                                            } else if (!link.startsWith("/") && link.endsWith("/index.html")) {
                                                link = "http://" + url.getHost() + "/" + link;
                                            } else {
                                                link = "http://" + url.getHost() + url.getPath().substring(0, url.getPath().lastIndexOf("/") + 1) + link.substring(link.indexOf("/") + 1);
                                            }
                                        } else if (link.startsWith("http://") && link.endsWith(".html")) {
                                            System.out.println("\t\t\tfoo");
                                        }
                                        if (!fetchedList.contains(link) && WebSiteGetter.threads.size() < WebSiteGetter.maxSize) {
                                            System.out.println("added " + link + " to fetch");
                                            WebPage p2 = new WebPage(new URL(link));
                                            WebSiteGetter.threads.add(p2);
                                            p2.start();
                                        }
                                    }
                                } else if(m.group(4).endsWith(".css")) {
                                    WebObject w = new WebObject(m.group(4).startsWith("http://") ? new URL(m.group(4)) : new URL("http://" + url.getHost() + m.group(4)), false);
                                    opgebouwdeContent += m.group(1) + m.group(2) + m.group(3) + "file://" + new File(".").getCanonicalPath() + "/" + url.getHost() + codeLink + m.group(5) + "\n";
                                    w.writeToFile();
                                }
                            }
                            if (!codeLink.startsWith("http://")) {
                                if (codeLink.endsWith("/")) {
                                    opgebouwdeContent += m.group(1) + m.group(2) + m.group(3) + "file://" + new File(".").getCanonicalPath() + "/" + url.getHost() + codeLink + "index.html" + m.group(5) + "\n";
                                } else {
                                    opgebouwdeContent += m.group(1) + m.group(2) + m.group(3) + "file://" + new File(".").getCanonicalPath() + "/" + url.getHost() + codeLink + m.group(5) + "\n";
                                }
                            } else {
                                opgebouwdeContent += m.group(1) + m.group(2) + m.group(3) + codeLink + m.group(5) + "\n";
                            }
                        } else {
                            if(m.group(4).endsWith(".jpg") || m.group(4).endsWith(".jpeg") || m.group(4).endsWith(".png") || m.group(4).endsWith(".gif") || m.group(4).endsWith(".bmp")){
                                URL newURL = new URL(codeLink.startsWith("/") ? "http://" + url.getHost() + codeLink : codeLink);
                                System.out.println("image --> " + codeLink);
                                if(m.group(4).startsWith("/")){
                                    opgebouwdeContent += m.group(1) + m.group(2) + m.group(3) + "file://" + new File(".").getCanonicalPath() + "/" + url.getHost() + codeLink + m.group(5) + "\n";
                                } else if(m.group(4).startsWith("http")){
                                    opgebouwdeContent += m.group(1) + m.group(2) + m.group(3) + "file://" + new File(".").getCanonicalPath() + "/" + url.getHost() + newURL.getPath() + m.group(5) + "\n";
                                }
                                WebObject wo = new WebObject(m.group(4).startsWith("http://") ? new URL(m.group(4)) : new URL("http://" + url.getHost() + m.group(4)), true);
                                wo.writeToFile();
                            }
                        }
                    }
                } else {
                    opgebouwdeContent += inputLine;
                }
            }
            System.out.println(url.toString() + " fetched");
        } catch (FileNotFoundException ex) {
            content = opgebouwdeContent.getBytes();
            writePage();
            WebSiteGetter.threads.remove(this);
            done = true;
            System.out.println("Thread stopped " + WebSiteGetter.threads.size());
        } catch (URISyntaxException ex) {
            ex.printStackTrace();
        }
        content = opgebouwdeContent.getBytes();
        writePage();
        WebSiteGetter.threads.remove(this);
        done = true;
        System.out.println("Thread stopped " + WebSiteGetter.threads.size());
    }

    /**
     * Command to write this page to disc.
     * @throws IOException
     */
    public void writePage() throws IOException {
        try {
            FileOutputStream foStream = new FileOutputStream(outputFile);
            foStream.write(content);
            foStream.close();
            done = true;
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}
